package br.edu.ufra.dao;

import java.lang.reflect.ParameterizedType;
import java.util.Collection;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

public abstract class BaseDAO<T> {
	protected Session session = null;
	protected Transaction transaction = null;
	protected boolean wasCreatedWithASession = false; 

	public BaseDAO() {
	}

	public BaseDAO(Session session){
		this.session = session; 
		this.wasCreatedWithASession = true;
	}

	public void save(T obj){
		if (!this.wasCreatedWithASession)
			this.session = HibernateSession.getSession();

		transaction = this.session.beginTransaction();
		this.session.save(obj);
		transaction.commit();

		if ((!this.wasCreatedWithASession) && (this.session != null)){
			this.session.close();
		}
	}

	public void update(T obj){
		if (!this.wasCreatedWithASession)
			this.session = HibernateSession.getSession();

		transaction = session.beginTransaction();
		this.session.update(obj);
		transaction.commit();

		if ((!this.wasCreatedWithASession) && (this.session != null)){
			this.session.close();
		}
	}

	public void delete(T obj){
		if (!this.wasCreatedWithASession)
			this.session = HibernateSession.getSession();

		transaction = session.beginTransaction();
		session.delete(obj);
		transaction.commit();

		if ((!this.wasCreatedWithASession) && (this.session != null)){
			this.session.close();
		}
	}

	@SuppressWarnings("unchecked")
	public Collection<T> findAll(){
		if (!this.wasCreatedWithASession)
			this.session = HibernateSession.getSession();

		Query query = session.createQuery("FROM " + getParametrizedClass().getName());
		Collection<T> objs = (Collection<T>)query.list();

		if ((!this.wasCreatedWithASession) && (this.session != null)){
			this.session.close();
		}

		return objs;
	}

	@SuppressWarnings("unchecked")
	public T findByPrimaryKey(Integer pk){
			if (!this.wasCreatedWithASession)
				this.session = HibernateSession.getSession();

			T obj = (T)session.get( getParametrizedClass(), pk);
			return obj;
	}              

	@SuppressWarnings("unchecked")
	protected Class<T> getParametrizedClass(){
		ParameterizedType tipoClassePai = (ParameterizedType)this.getClass().getGenericSuperclass();  
		
		return (Class<T>) tipoClassePai.getActualTypeArguments()[0];
	}
	
	public Session getSession() {
		return session;
	}
	public void setSession(Session session) {
		this.wasCreatedWithASession = true;
		this.session = session;		
	}
}